#include "stdafx.h"
#include "Database.h"
#include "GameManager.h"
#include "ObjectBattler.h"

const int GameManager::SkillSlotCount;
const int GameManager::ItemSlotCount;
const int GameManager::InitialGold = 1111;
const int GameManager::BattleCount;
const int GameManager::LevelCount;
bool GameManager::inBattle;
bool GameManager::newEquip;
bool GameManager::newSkill;

int GameManager::leaderId;
int GameManager::gold;
Skill* GameManager::skillSlots[SkillSlotCount];
Item* GameManager::itemSlots[ItemSlotCount]; 
int GameManager::battleRecord[BattleCount][LevelCount][2];

map<ItemBase*, int> GameManager::items = map<ItemBase*, int>();
ObjectActor* GameManager::leader;
map<int, ObjectActor> GameManager::actors;

const InputManager::KeyMap GameManager::skillSlotKeys[GameManager::SkillSlotCount] ={
	InputManager::KeyMap::Skill1,InputManager::KeyMap::Skill2,InputManager::KeyMap::Skill3,
	InputManager::KeyMap::Skill4,InputManager::KeyMap::Skill5 
};
const InputManager::KeyMap GameManager::itemSlotKeys[GameManager::ItemSlotCount] ={
	InputManager::KeyMap::Item1,InputManager::KeyMap::Item2,InputManager::KeyMap::Item3 
};

void GameManager::setupGame(int id = 0) {
	inBattle = false;
	leaderId = id;
	leader = getActor(id);
	gold = InitialGold;
	clearSkillSlots();
	clearItemSlots();
	initializeItems();
	initializeRecords();
}
void GameManager::setdownGame() {
	actors.clear();
	items.clear();
}
void GameManager::initializeItems() {
	gainItem(&(::items[0]), 3);
	gainItem(&(::items[3]), 3);
}
void GameManager::initializeRecords() {
	for (int i = 0; i < BattleCount; i++)
		for (int l = 0; l < LevelCount; l++)
			battleRecord[i][l][0] = battleRecord[i][l][1] = -1;
}
void GameManager::clearSkillSlots() {
	for (int i = 0; i < SkillSlotCount; i++) skillSlots[i] = NULL;
}
void GameManager::clearItemSlots() {
	for (int i = 0; i < ItemSlotCount; i++) itemSlots[i] = NULL;//pair<Item*, int>(NULL, 0);
}

Skill* GameManager::getSkillSlot(int id) {
	return skillSlots[id];
}
Item* GameManager::getItemSlot(int id) {
	Item* res = itemSlots[id];
	if (res != NULL && itemNum(res) <= 0) res = NULL;
	return res;
}
void GameManager::setSkillSlot(Skill* skill, int id) {
	skillSlots[id] = skill;
}
void GameManager::switchSkillSlot(Skill* skill, int id) {
	skillSlots[id] == skill ? clearSkillSlot(id) : setSkillSlot(skill,id);
}
void GameManager::clearSkillSlot(int id) {
	skillSlots[id] = NULL;
}

void GameManager::setItemSlot(Item* item, int id) {
	itemSlots[id] = item;// pair<Item*, int>(item, count);
}
void GameManager::switchItemSlot(Item* item, int id) {
	itemSlots[id] == item ? clearItemSlot(id) : setItemSlot(item, id);
}
void GameManager::clearItemSlot(int id) {
	itemSlots[id] = NULL;//.first = NULL;
}

void GameManager::useItemSlot(int count, int id) {
	Item* item = itemSlots[id];
	if (item = NULL) return;
	loseItem(item, count);
	if(itemNum(item)<=0)
		clearItemSlot(id);
}


int GameManager::getBattleScoreRecord(int id, int level) {
	return battleRecord[id][level][0];
}
int GameManager::getBattleScoreJudge(int id, int level) {
	return battleRecord[id][level][1];
}
void GameManager::setBattleScoreRecord(int id, int level, int record, int judge) {
	battleRecord[id][level][0] = max(battleRecord[id][level][0], record);
	if (battleRecord[id][level][1] < 0) battleRecord[id][level][1] = judge;
	else battleRecord[id][level][1] = min(battleRecord[id][level][1], judge);
}
bool GameManager::isBattleLevelPassed(int level) {
	for (int i = 0; i < BattleCount; i++)
		if (battleRecord[i][level][0] <= 0 ||
			battleRecord[i][level][1] == 6) return false;
	return true;
}

void GameManager::gainItem(ItemBase* item, int count, bool newEquip) {
	if (item->type >= 2 && newEquip) GameManager::newEquip = true;
	if (items.count(item)) items[item] += count;
	else items[item] = count;
}
void GameManager::loseItem(ItemBase* item, int count) {
	if (items.count(item)) {
		items[item] -= count;
		if (items[item] < 0) items[item] = 0;
	}
}
int GameManager::itemNum(ItemBase* item) {
	if (items.count(item)) return items[item];
	return 0;
}
bool GameManager::hasItem(ItemBase* item, bool include) {
	int num = itemNum(item);
	if (num > 0) return true;
	if (include && item->type>=2) {
		vector<Equip*> equips = leader->getEquipsWithoutNULL();
		for (int i = 0; i < equips.size(); i++)
			if (equips[i] == item) return true;
	}
	return false;
}
void GameManager::gainGold(int count) { 
	gold += count; 
}
void GameManager::loseGold(int count) { 
	gold -= count; if (gold < 0) gold = 0;
}

int GameManager::getGold() { return gold; }

vector<ItemBase*> GameManager::getItems() {
	vector<ItemBase*> res;
	map<ItemBase*, int>::iterator iit;
	for (iit = items.begin(); iit != items.end(); iit++)
		if ((*iit).second > 0)res.push_back((*iit).first);
	return res;
}

int GameManager::getLeaderId() { return leaderId; }

ObjectActor* GameManager::getLeader() { return leader; }

ObjectActor* GameManager::getActor(int id) {
	if (actors.count(id)) return &actors[id];
	actors[id] = ObjectActor(id);
	return &actors[id];
}

string GameManager::makeSaveData() {
	string data = ""; char data_c[50];
	sprintf_s(data_c, "%d\n", leaderId); data += data_c;
	sprintf_s(data_c, "%d\n", gold); data += data_c;

	map<ItemBase*, int>::iterator iit;
	sprintf_s(data_c, "%d\n", getItems().size()); data += data_c;
	for (iit = items.begin(); iit != items.end(); iit++) {
		int count = (*iit).second;
		if (count <= 0) continue;
		ItemBase* item = (*iit).first;
		sprintf_s(data_c, "%d %d %d\n", item->type, item->index, count);
		data += data_c;
	}
	for (int i = 0; i < SkillSlotCount; i++) {
		if(skillSlots[i] == NULL) sprintf_s(data_c, "%d ", -1);
		else sprintf_s(data_c, "%d ", skillSlots[i]->index);
		data += data_c;
	} data += '\n';
	for (int i = 0; i < ItemSlotCount; i++) {
		if (itemSlots[i] == NULL) sprintf_s(data_c, "%d ", -1);
		else sprintf_s(data_c, "%d ", itemSlots[i]->index);
		data += data_c;
	} data += '\n';

	for (int i = 0; i < BattleCount; i++) {
		for (int l = 0; l < LevelCount; l++) {
			sprintf_s(data_c, "%d %d ", battleRecord[i][l][0], battleRecord[i][l][1]); data += data_c;
		}
		data += '\n';
	} 

	map<int, ObjectActor>::iterator ait;
	sprintf_s(data_c, "%d\n", actors.size()); data += data_c;
	for (ait = actors.begin(); ait != actors.end(); ait++) {
		ObjectActor* actor = &((*ait).second);
		sprintf_s(data_c, "%d|", (*ait).first);
		data += data_c + actor->makeSaveData() + '\n';
	}
	return data;
}
void GameManager::loadSaveData(string data) {
	int vsize; int l = 0; // line
	int type, index, count; char data_c[50];
	vector<string> adataV; string adata;
	vector<string> dataV = split(data, "\n");
	sscanf_s(dataV[l++].c_str(), "%d", &leaderId);
	sscanf_s(dataV[l++].c_str(), "%d", &gold);
	sscanf_s(dataV[l++].c_str(), "%d", &vsize);
	for (int i = 0; i < vsize; i++) {
		sscanf_s(dataV[l++].c_str(), "%d %d %d", &type,&index,&count);
		ItemBase* item;
		switch (type) {
		case 0: item = &::items[index]; break; // Item
		case 2: item = &::weapons[index]; break; // Weapon
		case 3: item = &::armors[index]; break; // Armor
		}
		gainItem(item, count);
	}
	adata = dataV[l++]; adataV = split(adata, " ");
	for (int i = 0; i < SkillSlotCount; i++) {
		sscanf_s(adataV[i].c_str(), "%d", &index);
		if (index == -1) continue;
		setSkillSlot(&::skills[index], i);
	}
	adata = dataV[l++]; adataV = split(adata, " ");
	for (int i = 0; i < ItemSlotCount; i++) {
		sscanf_s(adataV[i].c_str(), "%d", &index);
		if (index == -1) continue;
		setItemSlot(&::items[index], i);
	}
	for (int i = 0; i < BattleCount; i++) {
		adata = dataV[l++]; adataV = split(adata, " ");
		for (int ll = 0; ll < LevelCount; ll++) {
			sscanf_s(adataV[ll<<1].c_str(), "%d", &battleRecord[i][ll][0]);
			sscanf_s(adataV[(ll<<1)+1].c_str(), "%d", &battleRecord[i][ll][1]);
		}
	}
	sscanf_s(dataV[l++].c_str(), "%d", &vsize);
	for (int i = 0; i < vsize; i++) {
		adata = dataV[l++];
		adataV = split(adata, "|");
		sscanf_s(adataV[0].c_str(), "%d", &index);
		actors[index] = ObjectActor();
		actors[index].loadSaveData(adataV[1]);
	}
	leader = getActor(leaderId);
	newEquip = newSkill = false;
}
